"""
Case Type   : mot
Case Name   : 关闭enable_mot_server参数，使用gs_basebackup备份数据恢复，成功
Create At   : 2025/4/9
Owner       : @li-xin12345
Description : (编译带mot，不编译ENABLE_X86_RDTSCP，对应转测包)
    1、设置enable_incremental_checkpoint=off，enable_mot_server=on
    2、建表
    3、执行备份
    4、删表，关闭enable_mot_server
    5、停库，使用备份目录启动数据库
    6、清理环境
Expect      :
    1、成功
    2、成功
    3、成功
    4、成功
    5、成功
    6、成功
History     :
"""

import os
import time
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger

primary_db_sh = CommonSH('PrimaryDbUser')
cluster_node_count = primary_db_sh.get_node_num()


@unittest.skipIf(3 > cluster_node_count, '不满足一主两备环境跳过')
class MotTest(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.std1_db_sh = CommonSH('Standby1DbUser')
        self.std2_db_sh = CommonSH('Standby2DbUser')
        self.pri_node_sh = Node('PrimaryDbUser')
        self.constant = Constant()
        self.common = Common()
        self.tb_name = 't_guc_mot_0037'
        self.view_name = 'v_guc_mot_0037'
        self.index_name = 'i_guc_mot_0037'
        self.backup_dir = 'f_guc_mot_0037'
        self.param_names = ['enable_incremental_checkpoint',
                            'enable_mot_server']
        self.label_name = 'l_guc_mot_0037'
        self.default_values = [self.common.show_param(i) for i in
                               self.param_names]
        self.backup_path = os.path.join(os.path.dirname(
            macro.DB_INSTANCE_PATH), self.backup_dir)

    def test_mot(self):
        text = '-----step1:设置enable_incremental_checkpoint=off，' \
               'enable_mot_server=on;expect:成功-----'
        self.log.info(text)
        res = primary_db_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f'{self.param_names[0]}=off')
        self.log.info(res)
        self.assertTrue(res, "执行gs_guc set失败，预期成功但未找到标志信息")
        res = primary_db_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f'{self.param_names[1]}=on')
        self.log.info(res)
        self.assertTrue(res, "执行gs_guc set失败，预期成功但未找到标志信息")
        res = primary_db_sh.restart_db_cluster()
        self.log.info(res)
        self.assertTrue(res, '执行失败：' + text)
        status = primary_db_sh.get_db_cluster_status()
        self.assertTrue("Normal" or "Degrade" in status)
        res = [self.common.show_param(i) for i in self.param_names]
        self.log.info(res)
        self.assertEqual(['off', 'on'], res, '执行失败：' + text)

        text = '-----step2:建表;expect:成功-----'
        self.log.info(text)
        sql = f'''drop foreign table if exists {self.tb_name} cascade;
        create foreign table {self.tb_name} (id int primary key, 
        name varchar(100) not null, age int not null default 0);
        create index {self.index_name} on {self.tb_name} (name);
        insert into {self.tb_name} (id, name, age) values (1, 'alice', 25), 
        (2, 'bob', 30),(3, 'charlie', 35);
        select * from {self.tb_name} where age > 30;
        update {self.tb_name} set age = 26 where id = 1;
        begin;
        insert into {self.tb_name} (id, name, age) values (4, 'david', 40);
        commit;
        create or replace view {self.view_name} as
        select id, name, age from {self.tb_name} where age > 30;
        select * from {self.view_name};
        '''
        sql_res = primary_db_sh.execut_db_sql(sql)
        self.log.info(sql_res)
        self.assertIn(self.constant.DROP_FOREIGN_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CREATE_FOREIGN_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CREATE_INDEX_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.INSERT_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.COMMIT_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CREATE_VIEW_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.assertIn('2 rows', sql_res, '执行失败：' + text)

        self.log.info('-----step3:执行备份-----')
        self.log.info('--新建目录--')
        cmd = f"rm -rf {self.backup_path};mkdir -p {self.backup_path};" \
              f"chmod 700 {self.backup_path};" \
              f"ls {os.path.dirname(macro.DB_INSTANCE_PATH)} | " \
              f"grep '{self.backup_dir}';"
        self.log.info(cmd)
        res = self.common.get_sh_result(self.pri_node_sh, cmd)
        self.assertIn(f'{self.backup_dir}', res, '执行失败：' + text)

        self.log.info('--执行备份--')
        cmd = f"source {macro.DB_ENV_PATH};" \
              f"gs_basebackup -D {self.backup_path} -Fp -X stream " \
              f"-p {self.pri_node_sh.db_port} -l {self.label_name}.bak " \
              f"-U {self.pri_node_sh.ssh_user} -w"
        res = self.common.get_sh_result(self.pri_node_sh, cmd)
        self.assertIn('base backup successfully', res, '执行失败：' + text)

        text = '-----step4:删表，关闭enable_mot_server;expect:成功-----'
        self.log.info(text)
        sql = f"drop foreign table {self.tb_name} cascade;checkpoint;"
        self.log.info(sql)
        sql_res = primary_db_sh.execut_db_sql(sql)
        self.log.info(sql_res)
        self.assertIn(self.constant.DROP_FOREIGN_SUCCESS_MSG, sql_res,
                      '执行失败：' + text)
        self.log.info('--等待集群数据同步--')
        flag = primary_db_sh.check_data_consistency()
        self.assertTrue(flag, '执行失败：' + text)

        res = primary_db_sh.execute_gsguc('set',
                                        self.constant.GSGUC_SUCCESS_MSG,
                                        f'{self.param_names[1]}=off')
        self.log.info(res)
        self.assertTrue(res, "执行gs_guc set失败，预期成功但未找到标志信息")
        res = primary_db_sh.restart_db_cluster()
        self.log.info(res)
        self.assertTrue(res, '执行失败：' + text)
        status = primary_db_sh.get_db_cluster_status()
        self.assertTrue("Normal" or "Degrade" in status)
        res = [self.common.show_param(i) for i in self.param_names]
        self.log.info(res)
        self.assertEqual(['off', 'off'], res, '执行失败：' + text)

        self.log.info('-----step5:停库,使用备份目录启动数据库;expect:成功-----')
        stop_res = primary_db_sh.stop_db_instance()
        self.assertIn(self.constant.GS_CTL_STOP_SUCCESS_MSG, stop_res,
                      '执行失败：' + text)

        self.log.info('--使用备份目录启动数据库;expect:成功--')
        start_res = primary_db_sh.start_db_instance(dn_path=self.backup_path)
        self.assertIn(self.constant.RESTART_SUCCESS_MSG, start_res,
                      '执行失败：' + text)

    def tearDown(self):
        text = '-----step6:清理环境; expect:成功-----'
        self.log.info(text)
        stop_res = primary_db_sh.stop_db_instance(dn_path=self.backup_path)
        self.log.info(stop_res)
        start_res = primary_db_sh.start_db_instance()
        self.log.info(start_res)

        status = primary_db_sh.get_db_cluster_status(param='status')
        self.log.info(status)
        if status is False:
            build_res1 = self.std1_db_sh.build_standby()
            self.assertIn(self.constant.BUILD_SUCCESS_MSG, build_res1)
            build_res2 = self.std2_db_sh.build_standby()
            self.assertIn(self.constant.BUILD_SUCCESS_MSG, build_res2)
            time.sleep(10)
            status = primary_db_sh.get_db_cluster_status(param='status')
            self.log.info(status)
        self.assertTrue(status)

        cmd = f'rm -rf {self.backup_path};' \
              f'if [ -d {self.backup_path} ]; ' \
              f'then echo "exists"; else echo "not exists"; fi'
        rm_res = self.common.get_sh_result(self.pri_node_sh, cmd)

        sql = f'drop foreign table if exists {self.tb_name} cascade;checkpoint;'
        drop_res = primary_db_sh.execut_db_sql(sql)
        self.log.info(drop_res)
        self.log.info('--等待集群数据同步--')
        flag = primary_db_sh.check_data_consistency()
        self.assertTrue(flag, '执行失败：' + text)

        res = [self.common.show_param(i) for i in self.param_names]
        self.log.info(res)
        if res != self.default_values:
            for i, param_name in enumerate(self.param_names):
                res = primary_db_sh.execute_gsguc(
                    'set', self.constant.GSGUC_SUCCESS_MSG,
                    f'{param_name}={self.default_values[i]}')
                self.log.info(res)
            restart_res = primary_db_sh.restart_db_cluster()
            self.log.info(restart_res)
            status = primary_db_sh.get_db_cluster_status()
            self.log.info(status)
            show_param = [self.common.show_param(i) for i in self.param_names]
            self.log.info(show_param)
            self.assertEqual(self.default_values, show_param,
                             '执行失败：' + text)

        self.assertIn(self.constant.GS_CTL_STOP_SUCCESS_MSG, stop_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.RESTART_SUCCESS_MSG, start_res,
                      '执行失败：' + text)
        self.assertEqual('not exists', rm_res, '文件删除失败')
        self.assertIn(self.constant.DROP_FOREIGN_SUCCESS_MSG, drop_res,
                      '执行失败：' + text)
        self.assertIn(self.constant.CHECKPOINT_SUCCESS_MSG, drop_res,
                      '执行失败：' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')